﻿#include "mydn.h"
#include "storage.h"
#include "htmlcxx/ParserDom.h"
#include "htmlcxx/utils.h"
#include "htmlcxx/wincstring.h"
#include "common/TSQLString.h"

using namespace htmlcxx;
extern "C"
{
#include "sqlite3/sqlite3.h"
};

CStorage::CStorage(const char* dbPath)
{
	m_sqlite3 = NULL;
	sqlite3_open(dbPath, &m_sqlite3);
}

CStorage::~CStorage()
{
	if(NULL != m_sqlite3)
	{
		sqlite3_close(m_sqlite3);
	}
}

/*
* 清空数据库
*/
bool CStorage::Create()
{
	const char*         pcreate     = "create table links("
		"keywords1 varchar(64),"
		"keywords2 varchar(64),"
		"keywords3 varchar(64),"
		"filter varchar(64),"
		"path varchar(256),"
		"location varchar(64),"
		"author varchar(32),"
		"file varchar(512) primary key"
		")";

	if(NULL == m_sqlite3)
		return false;
	// 创建表
	if(SQLITE_OK != sqlite3_exec(m_sqlite3, pcreate, NULL, NULL, NULL))
	{
		return false;
	}
	return true;
}

/*
* 添加一个HTML文件
*/
bool CStorage::AddHtml(const char *pfile, const char *pdata)
{
	HTML::ParserDom                 doc;
	tree<HTML::Node>::iterator      node;
	char                            szKey1[64]      = {0};
	char                            szKey2[64]      = {0};
	char                            szKey3[64]      = {0};
	char                            szFilter[64]    = {0};
	char                            szPath[256]     = {0};
	char                            szLocation[64]  = {0};
	char                            szAuthor[32]    = {0};
	char							szTitle[64]		= {0};

	if(NULL == m_sqlite3)
		return false;

	doc.parseTree(pdata);
	for(node = doc.getTree().begin()
		; node != doc.getTree().end()
		; node++)
	{
		if(!node->isTag())
			continue;

		std::string			tagName		= node->tagName();

		if(0 == strcasecmp("meta", tagName.c_str()))
		{
			std::map<std::string, std::string>::const_iterator	name;
			std::map<std::string, std::string>::const_iterator	content;

			node->parseAttributes();
			name = node->attributes().find("name");
			if(node->attributes().end() == name)
				continue;
			content = node->attributes().find("content");
			if(node->attributes().end() == content)
				continue;
			// 分析内容
			if(0 == strcasecmp("keywords", name->second.c_str()))
			{
				char*       pstart      = (char *)content->second.c_str();
				char*       pend        = pstart;

				pend = strchr(pend, ',');
				if(NULL == pend)
				{
					strcpy(szKey1, pstart);
					continue;
				}
				strncpy(szKey1, pstart, pend - pstart);
				pstart = ++pend;
				pend = strchr(pend, ',');
				if(NULL == pend)
				{
					strcpy(szKey2, pstart);
					continue;
				}
				strncpy(szKey2, pstart, pend - pstart);
				pstart = ++pend;
				pend = strchr(pend, ',');
				if(NULL == pend)
				{
					strcpy(szKey3, pstart);
					continue;
				}
				strncpy(szKey2, pstart, pend - pstart);
			}
			else if(0 == strcasecmp("filter", name->second.c_str()))
				strncpy(szFilter, content->second.c_str(), sizeof(szFilter));
			else if(0 == strcasecmp("path", name->second.c_str()))
				strncpy(szPath, content->second.c_str(), sizeof(szPath));
			else if(0 == strcasecmp("location", name->second.c_str()))
				strncpy(szLocation, content->second.c_str(), sizeof(szLocation));
			else if(0 == strcasecmp("author", name->second.c_str()))
				strncpy(szAuthor, content->second.c_str(), sizeof(szAuthor));
		}
		else if(0 == strcasecmp("title", tagName.c_str()))
		{
			int							nLen			= 0;
			int							nPos			= 0;

			nPos = node->offset() + strlen(node->text().c_str());
			nLen = node->length() - strlen(node->text().c_str()) - strlen(node->closingText().c_str());
			if(nLen < 0)
				continue;
			strncpy(szTitle, node->text().c_str() + nPos, (nPos > sizeof(szTitle))?sizeof(szTitle):nPos);
		}
		else if(0 == strcasecmp("body", tagName.c_str()))
			break;
	}
	// 操作SQL
	TSQLString<1024>            sql;
	char*                       perr        = NULL;

	sql.format("insert into links(keywords1, keywords2, keywords3, "
		"filter, path, location, author, file) values('%64s', '%64s',"
		"'%64s', '%64s', '%256s', '%64s', '%32s', '%512s')"
		, szKey1, szKey2, szKey3, szFilter, szPath, szLocation
		, szAuthor, pfile);
	DbgTrace(("execute \"%s\" failed: %s\n", (char *)sql, perr));
	if(SQLITE_OK != sqlite3_exec(m_sqlite3, (char *)sql, NULL, NULL, &perr))
	{
		return false;
	}
	return true;
}

/*
* 获取数据
*/
bool CStorage::GetJoinList(std::string &str)
{
	if(NULL == m_sqlite3)
	{
		return false;
	}

	char**          dbTable;
	int             nrows           = 0;
	int             ncolumns        = 0;
	int             nret            = 0;
	char*           perr            = NULL;

	nret = sqlite3_get_table(m_sqlite3
		, "select * from links"
		, &dbTable, &nrows, &ncolumns
		, &perr);
	if(SQLITE_OK != nret)
	{
		DbgTrace(("sqlite3_get_table failed: %s\n", perr));
		return false;
	}
	str = "[";
	for(int i = 0; i < nrows; i++)
	{
		TSQLString<1024>        arr;

		if(ncolumns < 8)
			continue;
		arr.format("['%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s']"
			, dbTable[ncolumns * i + 0]
		, dbTable[ncolumns * i + 1]
		, dbTable[ncolumns * i + 2]
		, dbTable[ncolumns * i + 3]
		, dbTable[ncolumns * i + 4]
		, dbTable[ncolumns * i + 5]
		, dbTable[ncolumns * i + 6]
		, dbTable[ncolumns * i + 7]);
		if(str.size() > 2)
			str += ",";
		str += (char *)arr;
	}
	sqlite3_free_table(dbTable);
	str += "]";
	return true;
}


